package com.crrc.util;

import javax.imageio.*;
import javax.imageio.stream.FileImageInputStream;
import javax.imageio.stream.FileImageOutputStream;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.MemoryCacheImageInputStream;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;

/**
 * 图片打水印工具类，  传入一个图片名称，传入一个图片路径 然后交给他处理就可以
 */
public class PictureWatermark {
    /**
     *
     * @param list 包含了文件名称以及文件路径
     * @param text 文字水印传值
     * @return
     * @throws IOException
     */
    public static synchronized File pictureWatermark(byte[] imgBytes, String text) throws IOException {
        BufferedImage read = null;
        ImageInputStream imageInputstream = new MemoryCacheImageInputStream(new ByteArrayInputStream(imgBytes));

        //根据图片文件获取读取器
        Iterator<ImageReader> it = ImageIO.getImageReaders(imageInputstream);
        System.out.println(it);
        while (it.hasNext()) {
            ImageReader imageReader = it.next();
            // 设置解码器的输入流
            imageReader.setInput(imageInputstream, true, true);
            // 图像文件格式后缀
            String suffix = imageReader.getFormatName().trim().toLowerCase();
            // 图像宽度
            int width = imageReader.getWidth(0);
            // 图像高度
            int height = imageReader.getHeight(0);
            System.out.printf("format %s,%dx%d\n", suffix, width, height);
            try {
                // 解码成功返回BufferedImage对象
                // 0即为对第0张图像解码(gif格式会有多张图像),前面获取宽度高度的方法中的参数0也是同样的意思
                read = imageReader.read(0, imageReader.getDefaultReadParam());
                System.out.println(read);
            } catch (Exception e) {
                imageReader.dispose();
                // 如果解码失败尝试用下一个ImageReader解码
            }
        }
        //检测读取器是否存在
        ImageReader imageReader = it.next();
        //设置读取器输入流
        imageReader.setInput(imageInputstream);
        //从读取器取BufferedImage，这里只有一个，所以可以直接写0
        BufferedImage bufferedImage = imageReader.read(0);
        //开始加水印
        {
            //取画笔
            Graphics2D graphics2d = bufferedImage.createGraphics();
            //设置画笔文字抗锯齿
            graphics2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            //将画笔移动到图片中央
            graphics2d.transform(AffineTransform.getTranslateInstance(bufferedImage.getWidth() / 2, bufferedImage.getHeight() / 2));
            //将画笔旋转一定弧度
            graphics2d.transform(AffineTransform.getRotateInstance(Math.toRadians(45)));
            //计算图片外切圆半径
            float radius = Double.valueOf(Math.sqrt(bufferedImage.getWidth() * bufferedImage.getWidth() + bufferedImage.getHeight() * bufferedImage.getHeight()) / 2).floatValue();
            //设置画笔要用的字体，这里可以设置字体样式和大小
            Font waterMarkerFont = new Font("微软雅黑", Font.PLAIN, bufferedImage.getHeight() / 25);
            //设置画笔字体
            graphics2d.setFont(waterMarkerFont);
            //设置画笔颜色
            graphics2d.setColor(Color.WHITE);
            //设置画笔操作透明度
            graphics2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.3F));
            //取画笔字体信息
            FontMetrics fontMetrics = graphics2d.getFontMetrics();
            //水印文字
            String waterMarker = text;
            //计算水印文字宽度，很多人卡在了这一步
            int stringWidth = fontMetrics.stringWidth(waterMarker);
            //循环添加水印，这里可以设置水印水平距离，单位：px
            for (float i = -radius; i <= radius; i += (stringWidth + bufferedImage.getHeight() / 25)) {
                //这里可以设置水印垂直距离，单位：px
                for (float j = -radius; j <= radius; j += (fontMetrics.getHeight() + bufferedImage.getHeight() / 25)) {
                    //画水印
                    graphics2d.drawString(waterMarker, i, j);
                }
            }
            //释放画笔资源
            graphics2d.dispose();
        }
        //根据图片文件读取器获取图片文件写入器
        ImageWriter imageWriter = ImageIO.getImageWriter(imageReader);
        File file = new File(UUID.randomUUID()+".jpg");
        //生成目标图片文件路径
        FileImageOutputStream fileOutputStream = new FileImageOutputStream(file);
        //设置写入器输出流
        imageWriter.setOutput(fileOutputStream);


        IIOImage iioImage = new IIOImage(bufferedImage, null, null);
        ImageWriteParam imageWriteParam = imageWriter.getDefaultWriteParam();
        //jpg格式图片可设置输出图片文件的质量
        if (imageReader.getFormatName().equals("JPEG")) {
            //这一行固定这样写，跟下一行搭配
            imageWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            //跟上一行搭配，设置输出图片文件的质量
            imageWriteParam.setCompressionQuality(0.947F);
        }
        //写文件
        imageWriter.write(null, iioImage, imageWriteParam);
        //关闭写入器
        imageWriter.dispose();
        //关闭读取器
        imageReader.dispose();

        imageInputstream.close();

        if(file == null){
            return null;
        }
        return file;
    }
}
